using System.Reflection;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SqlSugar;

namespace Digitalmes.Sugar;

/// <summary>
/// 工作单元筛选器
/// </summary>
public sealed class UnitOfWorkFilter : IAsyncActionFilter, IOrderedFilter
{
    public int Order => 100;

    private readonly ILogger _logger;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="sqlSugarClient"></param>

    public UnitOfWorkFilter(ILogger<UnitOfWorkFilter> logger)
    {
        _logger = logger;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // 获取动作方法描述器
        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
        var attribute = actionDescriptor?.MethodInfo.GetCustomAttribute<UnitOfWorkAttribute>(false);
        if (attribute == null)
        {
            _ = await next();
            return;
        }

        var sqlSugarClient = context.HttpContext.RequestServices.GetService<ISqlSugarClient>();
        if (sqlSugarClient is null)
        {
            return;
        }

        // 开启事务
        sqlSugarClient.Ado.BeginTran(attribute.IsolationLevel);

        // 调用方法
        var resultContext = await next();

        if (resultContext.Exception == null)
        {
            // 没有异常，尝试提交
            try
            {
                sqlSugarClient.Ado.CommitTran();
            }
            catch(Exception ex)
            {
                sqlSugarClient.Ado.RollbackTran();

                _logger.LogError(ex, "事务提交失败，Controller: {ControllerName}, Action: {ActionName}", actionDescriptor!.ControllerName, actionDescriptor!.ActionName);
            }
            finally
            {
                sqlSugarClient.Ado.Dispose();
            }
        }
        else
        {
            // 有抛出异常，直接回滚
            sqlSugarClient.Ado.RollbackTran();
            sqlSugarClient.Ado.Dispose();
        }
    }
}
